using System;
using System.Collections.Generic;
using System.Threading;
using OracleInternal.Common;
using OracleInternal.ConnectionPool;
using OracleInternal.TTC;

namespace OracleInternal.ServiceObjects
{
	internal class ClientInitiatedConnection
	{
		internal static int CIC_MAX_CONNECT_RETRIES = 5;

		internal static int CIC_INCREMENTAL_DELAY = 5;

		private OraclePoolManager m_opm;

		internal OracleConnectionImpl m_orclConnImpl;

		private TTCAQNotification m_aqNotif;

		private string m_listenerClientId;

		internal List<int> m_cqnRegistrations = new List<int>();

		internal bool m_bShutDown;

		internal ClientInitiatedConnection(string clientId, OraclePoolManager opm)
		{
			m_listenerClientId = clientId;
			m_opm = opm;
		}

		internal void ReconnectCallback()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReconnectCallback);
			}
			ThreadPool.QueueUserWorkItem(new WaitCallback(Reconnect), null);
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReconnectCallback);
			}
		}

		internal void Reconnect(object state)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReConnect);
			}
			for (int i = 1; i <= CIC_MAX_CONNECT_RETRIES; i++)
			{
				Thread.Sleep(i * 5000);
				try
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.SvcObj, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReConnect, $"Trial [{i}] to create CIC with ClientId: [{m_listenerClientId}]");
					}
					Connect();
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.SvcObj, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReConnect, $"Trial [{i}] to create CIC with ClientId: [{m_listenerClientId}] SUCCESS");
					}
					return;
				}
				catch (Exception ex)
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReConnect, $"Trial [{i}] to create CIC with ClientId: [{m_listenerClientId}] FAILED with Error: {ex.Message}");
					}
					if (CIC_MAX_CONNECT_RETRIES == i)
					{
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReConnect, $"FAILED to create CIC with ClientId: [{m_listenerClientId}] after [{i}] attempts. All attempts failed..");
						}
						NotifyRegistrationEndToAll();
						return;
					}
				}
				finally
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ReConnect);
					}
				}
			}
		}

		internal void NotifyRegistrationEndToAll()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.NotifyRegistrationEndToAll);
			}
			try
			{
				if (m_cqnRegistrations == null || m_cqnRegistrations.Count <= 0)
				{
					return;
				}
				int[] array = new int[m_cqnRegistrations.Count];
				m_cqnRegistrations.CopyTo(array);
				for (int i = 0; i < array.Length; i++)
				{
					try
					{
						if (m_orclConnImpl.m_bConnected)
						{
							OracleNotificationManager.UnRegisterFromChangeNotification(m_orclConnImpl, m_cqnRegistrations[i], m_listenerClientId);
						}
					}
					catch (Exception ex)
					{
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							string str = $"Internal unregister call failed for registration-id:{m_cqnRegistrations[i]} \n";
							str = str + "Exception Message: " + ex.Message;
							Trace.Write(OracleTraceLevel.Private, OracleTraceTag.SvcObj, OracleTraceClassName.OracleNotificationManager, OracleTraceFuncName.RegisterForChangeNotification, str);
						}
					}
					NotificationContext.EnqueueNotification(m_orclConnImpl, m_cqnRegistrations[i], (m_orclConnImpl.m_marshallingEngine != null) ? m_orclConnImpl.m_marshallingEngine.m_dbCharSetConv : null, 3, 0, null, bLastNotification: true);
				}
			}
			catch
			{
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.NotifyRegistrationEndToAll);
				}
			}
		}

		internal void Connect()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.Connect, "Attempting to create New Client Initiated Connection for Listener Client ID: " + m_listenerClientId);
			}
			try
			{
				m_orclConnImpl = new OracleConnectionImpl();
				m_orclConnImpl.StartSecureCQNListener(m_opm);
				m_orclConnImpl.m_listenerClientId = m_listenerClientId;
				m_aqNotif = new TTCAQNotification(m_orclConnImpl);
				m_aqNotif.SendRequest(TTCAQNotification.INIT_KPDNRREQ, m_listenerClientId);
				ThreadPool.QueueUserWorkItem(new WaitCallback(m_aqNotif.ReceiveResponse), this);
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.Connect);
				}
			}
		}

		internal void ShutDownListener()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ShutDownListener, "SHUTDOWN Client Initiated Connection for Listener Client ID: " + m_listenerClientId);
			}
			try
			{
				if (m_orclConnImpl != null)
				{
					if (m_aqNotif != null)
					{
						m_aqNotif.m_bShutDown = true;
					}
					m_orclConnImpl.m_oracleCommunication.Break();
				}
			}
			catch
			{
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.ClientInitiatedConnection, OracleTraceFuncName.ShutDownListener);
				}
			}
		}
	}
}
